import {Component, OnInit, Input, ElementRef, OnDestroy, AfterViewInit, Output, EventEmitter} from '@angular/core';
import {Map} from 'ol';
import {Image} from 'ol/layer';
import {ImageWMS} from 'ol/source';
import {HttpService} from '@kylin/http';
import {NzMessageService} from 'ng-zorro-antd';
import * as _ from 'lodash';
import {MapLegendService} from '../map-legend.service';
import {Vector as VectorSource} from 'ol/source';
import {Vector as VectorLayer} from 'ol/layer';
import {GeoJSON} from 'ol/format';
import {Router, ActivatedRoute, ParamMap, NavigationStart, NavigationEnd} from '@angular/router';
import {Overlay} from 'ol';


@Component({
    selector: 'kylin-map-layer-search',
    templateUrl: './map-layer-search.component.html',
    styleUrls: ['./map-layer-search.component.less']
})
export class MapLayerSearchComponent implements OnInit, OnDestroy, AfterViewInit {
    @Input() map: Map;
    searchResultContentState = false;
    searchResult = '';
    searchResultContentSwitch = true;
    labelSearch = null;
    layers: any = [];
    atlas: any = [];
    layerLabels: any = [];
    private colors = ['#6666CC', '#6699FF', '#66CCFF', '#66FFCC', '#9966CC', '#9999CC', '#99CC99', '#99FFFF', '#CC6699', '#CC9999'];
    private layersCollection = {};
    private atlasCollection = [];
    detailsParams: any;
    overlay: Overlay;
    areaAttributes = [];

    constructor(
        private http: HttpService,
        private elementRef: ElementRef,
        private nzMessageService: NzMessageService,
        private mapLegendService: MapLegendService,
        private activatedRoute: ActivatedRoute,
        private router: Router
    ) {
    }

    ngOnInit() {
        this.layerDataHandler(this.layerLabels, {isOpen: true});
        this.detailsByParams();
        this.router.events.subscribe(event => {
            if (event instanceof NavigationEnd) {
                if (event.url === '/home/front-page') {
                    setTimeout(() => {
                        const targetEle = document.getElementsByClassName('home-content')[0];
                        targetEle.removeEventListener('click', this.listener);
                        targetEle.addEventListener('click', this.listener);
                    }, 0)
                }
            }
        });
        this.mapClickEvent();
        this.popupInit();
    }

    ngAfterViewInit() {
        const targetEle = document.getElementsByClassName('home-content')[0];
        targetEle.addEventListener('click', this.listener);
        this.search({init: true});
    }

    ngOnDestroy() {
        const targetEle = document.getElementsByClassName('home-content')[0];
        targetEle.removeEventListener('click', this.listener);
    }

    popupInit() {
        const container: HTMLElement = document.querySelector('#popup');
        this.overlay = new Overlay(({
            element: container,
            autoPan: true,
            autoPanAnimation: {
                duration: 250   // 当Popup超出地图边界时，为了Popup全部可见，地图移动的速度.
            }
        }));
        this.map.addOverlay(this.overlay);
    }

    close() {
        this.overlay.setPosition(undefined);
    }

    private fetchParamsByUrl(url: string, target: string) {
        let result = '';
        const paramsUrl = url.substring(url.indexOf('?') + 1);
        const paramsArr = paramsUrl.split('&');
        paramsArr.map(value => {
            if (value.indexOf(target) !== -1) {
                result = value.substring(value.indexOf('=') + 1);
            }
        });
        return result;
    }

    mapClickEvent() {
        this.map.on('click', (evt) => {
            console.log(evt);
            const coordinate = evt.coordinate;
            const view = this.map.getView();
            const viewResolution = view.getResolution();
            const target = [];
            _.forIn(this.layersCollection, (value: any, key) => {
                const source = value.getSource();
                let url = '';
                try {
                    url = source.getGetFeatureInfoUrl(
                        evt.coordinate, viewResolution, view.getProjection(),
                        {'INFO_FORMAT': 'text/html', 'FEATURE_COUNT': 50, VERSION: '1.1.1', 'X': '50', 'Y': '50'});
                } catch (e) {
                    url = '';
                }
                if (url) {
                    const queryLayers = this.fetchParamsByUrl(url, 'layers=');
                    const targetUrl = url + '&QUERY_LAYERS=' + queryLayers;
                    target.push(targetUrl);
                }
            });

            this.atlasCollection.map((value) => {
                const source = value.getSource();
                let url = '';
                try {
                    url = source.getGetFeatureInfoUrl(
                        evt.coordinate, viewResolution, view.getProjection(),
                        {'INFO_FORMAT': 'text/html', 'FEATURE_COUNT': 50, VERSION: '1.1.1', 'X': '50', 'Y': '50'});
                } catch (e) {
                    url = '';
                }
                if (url) {
                    const queryLayers = this.fetchParamsByUrl(url, 'layers=');
                    const targetUrl = url + '&QUERY_LAYERS=' + queryLayers;
                    target.push(targetUrl);
                }
            });
            console.log(target);
            if (target.length > 0) {
                this.http.post('http://192.168.1.101:8000/layer/atlasAreasMapProperty', {areasUrl: target[0]})
                    .then(res => {
                        if (res.resp_code === '10000') {

                        } else {

                        }
                    })
                    .catch(err => {

                    })
            } else {

            }

            this.overlay.setPosition(coordinate);
            this.areaAttributes = [
                {field: 'fid', value: '1540868440723.2774'},
                {field: 'OBJECTID', value: '2774'},
                {field: '编号', value: '2812'},
                {field: 'pH', value: '7.9'},
                {field: '侵蚀类型', value: '1'},
                {field: '有机质', value: '25.9'}
            ];
        });
    }

    fetchLayersAttributes(urls: string[]) {

    }

    listener = () => {
        this.searchResultContentState = false;
    };

    stopPropagation($event) {
        $event.stopPropagation();
    }

    layerSearchInputFocus($event) {
        this.searchResultContentState = true;
    }

    search(options?) {
        this.reset('layers');
        this.http.get('http://192.168.1.100:8091/layer/search', {name: this.searchResult})
            .then(res => {
                if (res.resp_code === '10000') {
                    if (_.isEmpty(res.data.layerList) && _.isEmpty(res.data.layersList)) {
                        if (options.init) {

                        } else {
                            this.nzMessageService.warning('无相关图层,换个搜索词试试?');
                        }
                    }
                    const layersData = res.data.layerList.map((value) => {
                        return {layerName: value.layerName, layerId: value.layerId}
                    });
                    this.layers = this.layerDataHandler(layersData, {value: false});
                    const atlasData = res.data.layersList.map((value) => {
                        return {layersId: value.layersId, layersName: value.layersName}
                    });
                    this.atlas = this.layerDataHandler(atlasData, {value: false});
                    this.searchResultContentState = true;
                    if (options.init) {
                        this.searchResultContentState = false;
                    }
                } else {
                    this.searchResultContentState = false;
                }
            })
            .catch(err => {
                this.searchResultContentState = false;
            })
    }

    fetchLayerData(layerId: string, layersId?: string) {
        this.http.get(`http://192.168.1.100:8091/layer/${layerId}`)
            .then(res => {
                if (res.resp_code === '10000') {
                    res.data.map(e => {
                        if (!_.isEmpty(e.layerStyleList)) {
                            this.mapLegendService.addMapLegend(e.layerStyleList, {layerName: e.layerName});
                        }
                        if (_.indexOf([1, 2, 3], e.layerType) !== -1) { // 1,2,3是geoJson数据. 4,5,6是geo图层数据
                            this.addLayerByGeoJson({layerJson: e.layerJson, key: e.layerId}, layersId);
                        } else {
                            this.addLayerByWms({url: e.geoserverUrl, key: e.layerId}, layersId);
                        }
                    })
                }
            })
            .catch(err => {

            })
    }

    layerCheckboxChange(value, options) {
        if (value) {
            if (options.layerId) {
                this.addLayer(value, options);
            } else {
                this.fetchAtlasData(options);
            }
        } else {
            if (options.layerId) {
                this.removeLayer(options.layerId);
                this.mapLegendService.remove(options.layerId);
            } else {
                this.http.get('http://192.168.1.100:8091/layer/search', {layersId: options.layersId})
                    .then(res => {
                        res.data.layerList.map((e) => {
                            this.atlasCollection.map((v) => {
                                if ((e.layerId === v.layerId) && (options.layersId === v.layersId)) {
                                    this.map.removeLayer(v.layer);
                                }
                            })
                        });
                        _.remove(this.atlasCollection, (e) => {
                            return e.layersId === options.layersId;
                        })
                    })
                    .catch(err => {

                    })
            }
        }
    }

    private fetchAtlasData(options) {
        this.http.get('http://192.168.1.100:8091/layer/search', {name: this.searchResult, layersId: options.layersId})
            .then(res => {
                const layerIdList = [];
                res.data.layerList.map((e) => {
                    layerIdList.push(e.layerId);
                });
                this.fetchLayerData(layerIdList.toString(), options.layersId);
            })
            .catch(err => {

            })
    }

    private addLayer(value, options) {
        this.fetchLayerData(options.layerId);
    }

    private layerDataHandler(data: any[], options?: {}) {
        data.map((value, index) => {
            if (options) {
                _.forIn(options, (v, k) => {
                    value[k] = v;
                })
            }
            if (value.child) {
                this.layerDataHandler(value.child);
            } else {
                value['color'] = this.colors[index % 10];
            }
        });
        return data;
    }

    labelSearchButtonClick() {
        if (this.labelSearch) {
            this.reset('labels');
            this.http.get('http://192.168.1.100:8091/layer/searchLabel', {labelName: this.labelSearch})
                .then(res => {
                    if (res.resp_code === '10000') {
                        if (_.isEmpty(res.data)) {
                            this.nzMessageService.warning('无此标签');
                        } else {
                            const targetArr = [];
                            _.forIn(res.data, (value, key) => {
                                const child = _.remove(value.map((e) => {
                                    if (e) {
                                        return {layerName: e.layerName, layerId: e.layerId};
                                    }
                                }), (n) => {
                                    if (n) {
                                        return true;
                                    } else {
                                        return false;
                                    }
                                });
                                targetArr.push({name: key, child: child});
                            });
                            this.layerLabels = this.layerDataHandler(targetArr, {isOpen: true});
                        }
                    }
                })
                .catch(err => {

                })
        }
    }

    private addLayerByWms(options, layersId?: string) {
        const data = this.urlResolver(options.url);
        if (layersId) {
            const layer = new Image({
                source: new ImageWMS({
                    ratio: 1,
                    url: data.url,
                    params: {
                        format: 'image/png',
                        version: data.version,
                        style: '',
                        layers: data.layers,
                    }
                }),
                opacity: 0.7
            });
            const obj = {layersId: layersId, layerId: options.key, layer: layer};
            this.atlasCollection.push(obj);
            this.map.addLayer(obj.layer);
        } else {
            this.layersCollection[options.key] = new Image({
                source: new ImageWMS({
                    ratio: 1,
                    url: data.url,
                    params: {
                        format: 'image/png',
                        version: data.version,
                        style: '',
                        layers: data.layers,
                    }
                }),
                opacity: 0.7
            });
            this.map.addLayer(this.layersCollection[options.key]);
        }
    }

    addLayerByGeoJson(options, layersId?: string) {
        const layerJson = JSON.parse(options.layerJson);
        const vectorSource = new VectorSource({
            features: (new GeoJSON()).readFeatures(layerJson)
        });
        if (layersId) {
            const layer = new VectorLayer({
                source: vectorSource,
                // style: null
            });
            const obj = {layersId: layersId, layerId: options.key, layer: layer};
            this.atlasCollection.push(obj);
            this.map.addLayer(obj.layer);
        } else {
            this.layersCollection[options.key] = new VectorLayer({
                source: vectorSource,
                // style: null
            });
            this.map.addLayer(this.layersCollection[options.key]);
        }
    }

    removeLayer(key: string) {
        this.map.removeLayer(this.layersCollection[key]);
        delete this.layersCollection[key];
    }

    private urlResolver(url: string) {
        return {
            url: this.getQueryVariable('url', url),
            layers: this.getQueryVariable('layers', url),
            version: this.getQueryVariable('version', url)
        }
    }

    private getQueryVariable(variable: string, url: string) {
        const vars = url.split('&');
        if (variable === 'url') {
            return vars[0].split('?')[0];
        }
        for (let i = 0; i < vars.length; i++) {
            const pair = vars[i].split('=');
            if (pair[0] === variable) {
                return pair[1];
            }
        }
        return '';
    }

    reset(elementId: string) {
        switch (elementId) {
            case 'layers':
                this.layers.map(e => {
                    if (e.value === true) {
                        this.removeLayer(e.layerId);
                        this.mapLegendService.remove(e.layerId);
                        e.value = false;
                    }
                });
                this.atlas.map(e => {
                    if (e.value === true) {
                        this.mapLegendService.remove(e.layerId);
                        e.value = false;
                    }
                });
                this.atlasCollection.map(v => {
                    this.map.removeLayer(v.layer);
                });
                this.atlasCollection = [];
                break;
            case 'labels':
                this.layerLabels.map(e => {
                    e.child.map(value => {
                        if (value.value === true) {
                            this.removeLayer(value.layerId);
                            this.mapLegendService.remove(value.layerId);
                            value.value = false;
                        }
                    })
                });
                break;
        }
    }

    detailsByParams() {
        this.activatedRoute.queryParams.subscribe((params: ParamMap) => {
            this.detailsParams = params;
            if (params) {
                if (params['operation'] === 'layerDetails') {
                    const layerId = params['layerId'];
                    this.fetchLayerDataByParams(layerId);
                }
                if (params['operation'] === 'setDetails') {
                    const layersId = params['layersId'];
                    const layersName = params['layersName'];
                    this.fetchAtlasDataByParams(layersId, layersName);
                }
            }
        })
    }

    fetchLayerDataByParams(layerId: string) {
        this.http.get(`http://192.168.1.100:8091/layer/${layerId}`)
            .then(res => {
                if (res.resp_code === '10000') {
                    this.searchResultContentState = true;
                    this.layers = [{
                        value: true,
                        layerName: res.data[0].layerName,
                        layerId: layerId,
                        color: this.colors[0]
                    }];
                    res.data.map(e => {
                        if (!_.isEmpty(e.layerStyleList)) {
                            this.mapLegendService.addMapLegend(e.layerStyleList, {layerName: e.layerName});
                        }
                        if (_.indexOf([1, 2, 3], e.layerType) !== -1) { // 1,2,3是geoJson数据. 4,5,6是geo图层数据
                            this.addLayerByGeoJson({layerJson: e.layerJson, key: e.layerId});
                        } else {
                            this.addLayerByWms({url: e.geoserverUrl, key: e.layerId});
                        }
                    })
                }
            })
            .catch(err => {

            })
    }

    fetchAtlasDataByParams(layersId: string, layersName: string) {
        this.http.get('http://192.168.1.100:8091/layer/search', {layersId: layersId})
            .then(res => {
                this.searchResultContentState = true;
                this.atlas = [{
                    value: true,
                    layersName: layersName,
                    layersId: layersId,
                    color: this.colors[0]
                }];
                const layerIdList = [];
                res.data.layerList.map((e) => {
                    layerIdList.push(e.layerId);
                });
                this.fetchLayerData(layerIdList.toString());
            })
            .catch(err => {

            })
    }
}
